package com.agent;

import java.lang.instrument.Instrumentation;
import java.lang.management.ManagementFactory;

import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import com.agent.environ.AgentLoader;
import com.agent.environ.MyAtmApplication;
import com.agent.mbean.AgentManagement;
import com.agent.mbean.AgentManagementMBean;
import com.agent.socket.StartupUtil;
import com.agent.transformer.AtmTransformer;

/**
 * Hello world!
 *
 */
public class StartApp 
{
	 // Instance of AgentManagement MBean
    private static AgentManagement mgmtBean;
    
    public static void main( String[] args )
    {
    	 if(args[0].equals("StartMyAtmApplication")) {
             new MyAtmApplication().run(args);
         } else if(args[0].equals("LoadAgent")) {
        	 try {
        		 new AgentLoader().run(args);
        	 }catch (Exception e) {
				// TODO: handle exception
        		 e.printStackTrace();
			}
         }
    	 System.out.println("start all success......");
    }
    
    
    public static void premain(String agentArgs, Instrumentation inst) {
    		  
    			System.out.println("[Agent] In premain method");
    		    String className = "com.agent.application.TestStartApp";
    		    transformClass(className,inst);
    		    registerMBean();
    		    startCommond();
    		}
    
    public static void agentmain(
    			String agentArgs, Instrumentation inst) {
    		    System.out.println("[Agent] In agentmain method");
    		    String className = "com.agent.application.TestStartApp";
    		    transformClass(className,inst);
    		    registerMBean();
    		    startCommond();
    		}
    
    private static void transformClass(String className, Instrumentation instrumentation) {
    		    Class<?> targetCls = null;
    		    ClassLoader targetClassLoader = null;
    		    // see if we can get the class using forName
    		    try {
    		        targetCls = Class.forName(className);
    		        targetClassLoader = targetCls.getClassLoader();
    		        transform(targetCls, targetClassLoader, instrumentation);
    		        return;
    		    } catch (Exception ex) {
    		    	System.out.println("error Class [{}] not found with Class.forName");
    		    }
    		    // otherwise iterate all loaded classes and find what we want
    		    for(Class<?> clazz: instrumentation.getAllLoadedClasses()) {
    		        if(clazz.getName().equals(className)) {
    		            targetCls = clazz;
    		            targetClassLoader = targetCls.getClassLoader();
    		            transform(targetCls, targetClassLoader, instrumentation);
    		            return;
    		        }
    		    }
    		    throw new RuntimeException(
    		      "Failed to find class [" + className + "]");
    		}
    		 
    		private static void transform(
    		  Class<?> clazz, 
    		  ClassLoader classLoader,
    		  Instrumentation instrumentation) {
		AtmTransformer dt = new AtmTransformer(clazz.getName(), classLoader);
    		    instrumentation.addTransformer(dt, true);
    		    try {
    		        instrumentation.retransformClasses(clazz);
    		    } catch (Exception ex) {
    		        throw new RuntimeException(
    		          "Transform failed for: [" + clazz.getName() + "]", ex);
    		    }
    		}
    		
    		 private static void registerMBean() {
    		        if (mgmtBean == null) {
    		            mgmtBean = new AgentManagement();
    		            // Register MBean with MBean Server
    		            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    		            try {
    		                ObjectName name = new ObjectName(AgentManagementMBean.JMX_BEAN);
    		                if (mbs.isRegistered(name)) {
    		                    mbs.unregisterMBean(name);
    		                }
    		                mbs.registerMBean(mgmtBean, name);
    		            } catch (JMException ex) {
    		                ex.printStackTrace();
    		            }
    		        }
    		        }
    		 
    		 private static void startCommond() {
    			 StartupUtil.startApplication(9999);
    		 }
}
